'''7.2.1 文件的打开与关闭'''
# 将数据写入到文件之前需要先打开文件,数据写入完毕后需要将文件关闭以释放计算机内存.
'''1. 打开文件'''
# open()
# 语法格式: open(file,mode='r',encoding=None)
# open()函数中的参数file用于接收文件名或文件路径:参数encoding用于指定文件的编码格式:参数mode用于设置文件的打开模式
'''
打开模式   名称           描述 
r/rb     只读模式       以只读模式打开文本文件/二进制文件,若文件不存在,文件打开失败
w/wb     只写模式       以只写模式打开文本文件/二进制文件,若文件已存在,则重写文件,否则创建新文件
a/ab     追加模式       以追加方式打开文本文件/二进制文件,只允许在该文件末尾追加数据,若文件不存在,则创建新文件
r+/rb+   读取(更新)模式  以读写方式打开文本文件/二进制文件,若文件不存在,文件打开失败
w+/wb+   写入(更新)模式  以读写方式打开文本文件/二进制文件,若文件已存在,则重写文件,否则创建新文件
a+/ab+   追加(更新)模式  以读写方式打开文本文件/二进制文件,只允许在文件末尾追加数据,若文件不存在,则创建新文件
'''
# 若open()函数调用成功,返回一个文件对象
# file1 = open('E:\\a.txt')  # 以只读方式打开E盘中的文本文件a.txt
file2 = open('b.txt','w')  # 以只写方式打开当前目录价中的文本文件b.txt
file3 = open('c.txt','w+')  # 以读写方式打开当前目录中的文本文件c.txt
file4 = open('d.txt','wb+')  # 以读写方式打开当前目录中的二进制文件d.txt

# 2. 关闭文件
# file。close()
file2.close()
file3.close()
file4.close()
# with open
with open('b.txt') as f:
    pass

'''7.2.2 文件的读写'''
# 1. 读取文件
# 1.1 resd()方法
# read()方法可以从指定文件中读取指定字节的数据,其语法格式如下:
# read(n=-1)
# 以上格式中的参数n用于设置读取数据的字节数,若未提供或设置为-1,则一次读取并返回文件中的所有数据
with open('e.txt',mode='r',encoding='UTF-8') as t:
    print(t.read(2)) # 读取2个字节的数据并打印
    print(t.read())  # 读取剩余全部数据并打印

# 1.2 readline()方法
# readline()方法可以从指定文件中读取一行数据,其语法格式如下:
# readline()
with open('e.txt',mode='r',encoding='UTF-8') as t:
    print(t.readline())
    print(t.readline())
    print(t.readline())  # 从第一行开始,一次读取一行,依次往下读取

# 1.3 readlines()方法
# readlines()方法可以一次性读取文件中的所有数据,若读取成功返回一个列表,文件中的每一行对应列表中的一个元素.语法格式如下
# readlines(hint=-1)
# 以上格式中参数hint的单位为字节,它用于控制要读取的行数,如果行中的数据的总大小超出了hint字节,readlines()不会读取更多的行
with open('e.txt',mode='r',encoding='UTF-8') as t:
    print(t.readlines())
with open('e.txt', mode='r', encoding='UTF-8') as t: # 一次打开读取完毕后要再次打开读取,否则从第一次打开后读取到的位置继续读取
    print(t.readlines(8)) # 只要字节数到达了那一行,还是会把那一行完整的读出来

'''2.写文件'''
# 2.1 write()方法
# write()方法可以将指定字符串写入文件,其语法格式如下
# write(data)
# 以上格式中的参数data表示要写入文件的数据,若数据写入成功,write()方法会返回本次写入文件的数据的字节数
string = 'Here we are all,by day; by night' # 字符串
with open('white_file.txt',mode='w',encoding='utf-8') as w: # 以写入方式打开,若无文件名,则创建新文件
    size = w.write(string) # 写入字符串
    print(size)  # 打印字节数

# 2.2 writelines()方法
# writelines()方法用于将行列表写入文件,其语法格式如下:
# writelines(lines)
# 以上格式中的参数lines表示要写入文件中的数据,该参数可以是一个字符串或字符串列表.需要说明的是,若写入文件的数据在文件中需要换行,应显示指定换行符
string = 'Here we are all,by day:\nby night we are hurld by dreams'\
         'each one into a several world'  # 当 \ 出现在代码行末尾时，表示将下一行代码视为同一行（仅用于代码排版，不影响字符串内容）。
with open('file_writelines.txt',mode='w',encoding='utf-8') as wl:
    wl.writelines(string)
'''编码方式
支持语言   字符范围   字节长度（典型）  特点

ASCII 英文、数字、符号 0-127 1字节 最基础，仅支持英文字符
ISO-8859-1  西欧语言  0-255  1字节  ASCII扩展，支持拉丁字符
GB2312  简体中文  约7000+汉字  1字节（ASCII）<br>2字节（中文）  中国国家标准，兼容ASCII
GBK  简体中文、繁体中文  约21000+汉字  1字节（ASCII）<br>2字节（中文）  GB2312扩展，支持更多汉字
Big5  繁体中文  约13000+汉字  1字节（ASCII）<br>2字节（中文）  台湾地区常用编码
UTF-8  全球语言（Unicode）  全Unicode字符集  1-4字节（变长）  兼容ASCII，互联网通用编码
UTF-16  全球语言（Unicode）  全Unicode字符集  2字节或4字节（变长）  大端/小端可选，适合内存操作
UTF-32  全球语言（Unicode）  全Unicode字符集  4字节（固定）  固定长度，处理简单但空间效率低'''

'''7.2.3 文件的定位读写'''
'''
   在文件的一次大开口与关闭之间进行的读写操作是连续的,程序总是从上次读写的位置继续向下进行读写操作.
   实际上,每个文件对象都有一个称为 文件读写位置 的方法,以实现文件的定位读写
'''
'''
文件读写位置默认为0,即读写位置默认在文件首部.Python提供了一些获取与修改文件读写位置的方法,已实现文件的定位读写
'''

# 3.1 tell()方法
# tell()方法用于获取文件当前的读写位置
with open('file_writelines.txt',mode='r',encoding='utf-8') as f:
    print(f.tell()) # 获取文件读写位置
    print(f.read(5)) # 利用read()方法移动文件读写位置
    print(f.tell()) # 再次获取文件读写位置
# 由代码运行结果可知,tell()方法第一次获取到的文件读写位置为0,第2次获取的文件读写位置为5

# 3.2 seek()方法
# 程序一般顺序读取文件这种的内容,但并非每次读写都需要从当前位置开始,seek()方法可以控制文件读写的位置,实现文件的随机读写.
# seek()方法的语法格式如下:
# seek(offset,from)
# seek()方法中的参数offset表示偏移量,即读写位置需要移动的字节数:from用于指定文件的读写位置,该参数的取值为0,1,2,代表的含义如下
# 0:表示文件开头
# 1:表示使用当前读写位置
# 2:表示文件末尾
with open('file_seek.txt',mode='r',encoding='utf-8') as f:
    print(f.tell())
    print(f.seek(5,0))
# with open('file_seek.txt', mode='r', encoding='utf-8') as f:
#     print(f.seek(5, 1))
with open('file_seek.txt', mode='r', encoding='utf-8') as f:
    print(f.seek(0, 2)) #f.seek(offset, 2),2表示从文件末尾开始定位其中 offset 必须为 0（如 f.seek(0, 2) 是允许的，表示跳到文件末尾）。
'''
在 文本模式（如 'r' 或 'w'）下打开文件时，Python 不支持 seek(offset, 1)（即相对当前位置的偏移）。
只有用 二进制模式（如 'rb'、'wb' 或 'r+b'）打开文件时，才允许任意偏移的 seek 操作。
'''
'''
当用文本模式（如 "r" 或 "w"）打开文件时，Python 禁止以下操作：
f.seek(offset, 2)  # 2 表示从文件末尾开始定位其中 offset 必须为 0（如 f.seek(0, 2) 是允许的，表示跳到文件末尾）。
二进制模式才能自由定位只有以二进制模式（如 "rb"、"wb"）打开文件时，才允许从文件末尾进行任意偏移的 seek 操作。
'''
